/***
 * @Description:
 * @Author: LI Yihong
 * @Email: liyh@jihua.ac.cn
 * @Date: 2024-10-23 16:43:07
 * @LastEditTime: 2024-10-23 16:43:08
 * @LastEditors: LI Yihong
 * @FilePath: \STM32F407_Board\applications\I2C\I2C.hpp
 */
#pragma once
#include <rtdevice.h>
#include <memory>
#include <string>
#include <vector>
#include <board.h>
#include "cxx_thread.h"
#include <rtdevice.h>
#include <rtdbg.h>

#define SET_SDA(ops, val) ops->set_sda(ops->data, val)
#define SET_SCL(ops, val) ops->set_scl(ops->data, val)
#define GET_SDA(ops) ops->get_sda(ops->data)
#define GET_SCL(ops) ops->get_scl(ops->data)
#define SDA_L(ops) SET_SDA(ops, 0)
#define SDA_H(ops) SET_SDA(ops, 1)
#define SCL_L(ops) SET_SCL(ops, 0)

using namespace rtthread;
using namespace std;

class I2C : public Thread
{
public:
    using Thread::Thread;
    bool i2cInit(const string &busName);
    bool send(const rt_uint16_t &addr, const vector<rt_uint8_t> &data);
    bool sendByte(const rt_uint16_t &addr, const rt_uint8_t &data, bool startFlag = 1, bool stopFlag = 1);
    bool recv(const rt_uint16_t &addr, vector<rt_uint8_t> &data, const rt_uint32_t &count);
    bool recvByte(const rt_uint16_t &addr, rt_uint8_t &data, bool startFlag = 1, bool stopFlag = 1, bool ackFlag = 1);
    bool recvByteNoAck(const rt_uint16_t &addr, rt_uint8_t &data);

    virtual void run(void *parameter) = 0;

protected:
    string I2C_BUS_NAME;
    rt_i2c_bus_device *i2c_bus;
};

class I2C_Bit
{
public:
    static void i2c_delay(struct rt_i2c_bit_ops *ops);
    static void i2c_delay2(struct rt_i2c_bit_ops *ops);
    static rt_err_t SCL_H(struct rt_i2c_bit_ops *ops);
    static void i2c_start(struct rt_i2c_bit_ops *ops);
    static void i2c_restart(struct rt_i2c_bit_ops *ops);
    static void i2c_stop(struct rt_i2c_bit_ops *ops);
    static rt_bool_t i2c_waitack(struct rt_i2c_bit_ops *ops);
    static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data);
    static rt_int32_t i2c_readb(struct rt_i2c_bus_device *bus);
    static rt_size_t i2c_send_bytes(struct rt_i2c_bus_device *bus, struct rt_i2c_msg *msg);
    static rt_err_t i2c_send_ack_or_nack(struct rt_i2c_bus_device *bus, int ack);
    static rt_size_t i2c_recv_bytes(struct rt_i2c_bus_device *bus, struct rt_i2c_msg *msg);
    static rt_int32_t i2c_send_address(struct rt_i2c_bus_device *bus, rt_uint8_t addr, rt_int32_t retries);
    static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, struct rt_i2c_msg *msg);
    static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num);
};
